package com.ruoyi.gpt.controller;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Arrays;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.core.domain.model.WxGptUser;
import com.ruoyi.common.core.service.ConfigService;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.core.domain.vo.ConfigVo;
import com.ruoyi.core.service.IConfigService;
import com.ruoyi.gpt.constants.GptGoodsType;
import com.ruoyi.gpt.constants.PayStatusConstants;
import com.ruoyi.gpt.domain.bo.GptUserBo;
import com.ruoyi.gpt.domain.vo.GptGoodsVo;
import com.ruoyi.gpt.domain.vo.GptUserVo;
import com.ruoyi.gpt.service.IGptGoodsService;
import com.ruoyi.gpt.service.IGptUserService;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.gpt.domain.vo.GptOrderVo;
import com.ruoyi.gpt.domain.bo.GptOrderBo;
import com.ruoyi.gpt.service.IGptOrderService;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * Gpt订单列表
 *
 * @author ztx
 * @date 2023-04-10
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/gpt/gptOrder")
@Slf4j
public class GptOrderController extends BaseController {

    private final IGptOrderService iGptOrderService;
    private final IGptGoodsService iGptGoodsService;

    private final IConfigService configService;
    private final WxPayService wxPayService;

    private final IGptUserService iGptUserService;

    /**
     * 查询Gpt订单列表列表
     */
    @SaCheckPermission("gpt:gptOrder:list")
    @GetMapping("/list")
    public TableDataInfo<GptOrderVo> list(GptOrderBo bo, PageQuery pageQuery) {
        return iGptOrderService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出Gpt订单列表列表
     */
    @SaCheckPermission("gpt:gptOrder:export")
    @Log(title = "Gpt订单列表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(GptOrderBo bo, HttpServletResponse response) {
        List<GptOrderVo> list = iGptOrderService.queryList(bo);
        ExcelUtil.exportExcel(list, "Gpt订单列表", GptOrderVo.class, response);
    }

    /**
     * 获取Gpt订单列表详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("gpt:gptOrder:query")
    @GetMapping("/{id}")
    public R<GptOrderVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(iGptOrderService.queryById(id));
    }

    /**
     * 新增Gpt订单列表
     */
    @SaCheckPermission("gpt:gptOrder:add")
    @Log(title = "Gpt订单列表", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody GptOrderBo bo) {
        return toAjax(iGptOrderService.insertByBo(bo));
    }
    /**
     * 创建订单
     */
    @RepeatSubmit()
    @PostMapping("/createOrder")
    public R<Object> create(@RequestBody GptOrderBo gptOrderBo) throws WxPayException {
        if(ObjectUtil.isNull(gptOrderBo.getId())){
            return R.fail("商品id 不能为空");
        }
        GptOrderBo bo = new GptOrderBo();
        // 根据token获取登录用户
        WxGptUser wxGptUser = getWxGptUser();
        if(ObjectUtil.isNull(wxGptUser)){
            return R.fail("用户未登录");
        }
        bo.setUserId(wxGptUser.getUserId()); // 下单用户id
        bo.setAppid(wxGptUser.getAppid());
        bo.setIsPay("0");// 未支付
        bo.setStatus(PayStatusConstants.NO_PAY);// 订单状态未支付
        // 根据id 查询商品信息
        GptGoodsVo gptGoodsVo = iGptGoodsService.queryById(gptOrderBo.getId());
        if(ObjectUtil.isNull(gptGoodsVo)){
            return R.fail("商品不存在");
        }
        bo.setGoodsId(gptGoodsVo.getId());
        bo.setGoodsName(gptGoodsVo.getGoodsName());
        bo.setSalesPrice(gptGoodsVo.getSalesPrice());
        bo.setGoodsPic(gptGoodsVo.getGoodsPic());
        bo.setGoodsType(gptGoodsVo.getGoodsType());
        Integer goodsValueCounts = gptGoodsVo.getGoodsValueCounts();
        //专成long类型
        if(ObjectUtil.isNotNull(goodsValueCounts)){
            long goodsValueCountsLong = goodsValueCounts.longValue();
            bo.setGoodsValueCounts(goodsValueCountsLong);
        }
        bo.setGoodsValueTimes(gptGoodsVo.getGoodsValueTimes());


        Boolean aBoolean = iGptOrderService.insertByBo(bo);
        if(aBoolean){
            // 订单创建成功 , 调用微信下单
            Object order = unifiedOrder(bo, wxGptUser);
            return R.ok(order);
        }
        return R.fail("创建订单失败");
    }
    /**
     * 统一下单
     */
    private Object unifiedOrder(GptOrderBo bo, WxGptUser wxGptUser) throws WxPayException {
//        this.wxPayService.switchoverTo(bo.getAppid());
        this.wxPayService.switchoverTo("wx4435c9a369748ae4");
        ConfigVo configVo = configService.queryByAppid(bo.getAppid());
        if(ObjectUtil.isNull(configVo)){
            return R.fail("配置信息不存在");
        }
        BigDecimal salesPrice = bo.getSalesPrice();
        // 转成分
        BigDecimal multiply = salesPrice.multiply(new BigDecimal(100));
        //转成整数
        int totalFee = multiply.intValue();

        String body = bo.getGoodsName().length() > 40 ? bo.getGoodsName().substring(0,39) : bo.getGoodsName();
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
            .body(body)
            .totalFee(totalFee)
            .spbillCreateIp(wxGptUser.getIpaddr())
            .notifyUrl(configVo.getRedirectUrl()) // 回调地址
//            .tradeType(WxPayConstants.TradeType.JSAPI)
            .tradeType(WxPayConstants.TradeType.NATIVE)
            .productId(bo.getGoodsId().toString())
//            .openid(wxGptUser.getOpenid())
            .outTradeNo(bo.getId().toString())
            .build();
        return this.wxPayService.createOrder(wxPayUnifiedOrderRequest);
    }

    /**
     * 支付回调
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @PostMapping("/notify/order")
    @SaIgnore
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        log.info("支付回调:"+xmlData);
        WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
        log.info("支付结果：{}", notifyResult);
        // TODO 根据自己业务场景需要构造返回对象
        String outTradeNo = notifyResult.getOutTradeNo();
        GptOrderVo gptOrderVo = iGptOrderService.queryById(Long.valueOf(outTradeNo));
        if(ObjectUtil.isNull(gptOrderVo)){
            return WxPayNotifyResponse.fail("订单不存在");
        }
        if(!PayStatusConstants.NO_PAY.equals(gptOrderVo.getStatus())){
            return WxPayNotifyResponse.fail("订单已支付");
        }
        //判断是否支付成功
        if(!WxPayConstants.ResultCode.SUCCESS.equals(notifyResult.getResultCode())){
            return WxPayNotifyResponse.fail(notifyResult.getReturnMsg());
        }
        //判断订单金额是否一致
        BigDecimal totalFee = BigDecimal.valueOf(notifyResult.getTotalFee());
        BigDecimal salesPrice = gptOrderVo.getSalesPrice();
        BigDecimal multiply = salesPrice.multiply(new BigDecimal(100));
        int totalFeeInt = multiply.intValue();
        if(totalFeeInt != totalFee.intValue()){
            return WxPayNotifyResponse.fail("订单金额不一致");
        }
        // 判断订单是不是未支付状态
        if(!PayStatusConstants.NO_PAY.equals(gptOrderVo.getStatus()) || !"0".equals(gptOrderVo.getIsPay())){
            return WxPayNotifyResponse.fail("订单已支付");
        }
        // 修改订单状态
        iGptOrderService.changeOrderStatus(gptOrderVo);

        return WxPayNotifyResponse.success("成功");
    }

    /**
     * 修改Gpt订单列表
     */
    @SaCheckPermission("gpt:gptOrder:edit")
    @Log(title = "Gpt订单列表", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody GptOrderBo bo) {
        return toAjax(iGptOrderService.updateByBo(bo));
    }

    /**
     * 删除Gpt订单列表
     *
     * @param ids 主键串
     */
    @SaCheckPermission("gpt:gptOrder:remove")
    @Log(title = "Gpt订单列表", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(iGptOrderService.deleteWithValidByIds(Arrays.asList(ids), true));
    }
}
